home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / newsgrp / group93c.txt / 000101_icon-group-sender _Sun Nov 21 07:54:22 1993.msg < prev    next >
Internet Message Format  |  1994-02-02  |  33KB

  1. Received: by cheltenham.cs.arizona.edu; Tue, 23 Nov 1993 18:19:26 MST
  2. Date: 21 Nov 93 07:54:22 GMT
  3. From: noc.near.net!news.delphi.com!usenet@uunet.uu.net  (Will Mengarini)
  4. Organization: Delphi Internet
  5. Subject: Re: dos executables from icon
  6. Message-Id: <931121.10462.MENGARINI@delphi.com>
  7. References: <93312.000307U47041@uicvm.uic.edu>, <931114.21573.MENGARINI@delphi.com>, <casCGMCEp.G1I@netcom.com>
  8. Sender: icon-group-request@cs.arizona.edu
  9. To: icon-group@cs.arizona.edu
  10. Status: R
  11. Errors-To: icon-group-errors@cs.arizona.edu
  12.  
  13. This is the source code of a method for producing executable MS-DOS *.Exe
  14. files from Icon programs using the Icon interpretive system (IconT & IconX).
  15. It should be Makeable with 16-bit or 32-bit compilers on any computer that
  16. can Make the Icon interpretive system itself.
  17.  
  18. This is a modification of the source code for Version 8.8 of Icon for MS-DOS.
  19. That distribution's *.LZH archives have timestamps 3/22/93 03:17..03:19.
  20. It was developed under Borland C++ v3.1 in Sep 93, & has been in regular
  21. use since then for production of directly-executable MS-DOS Icon programs.
  22.  
  23. IconT usage remains unchanged except for 2 things.
  24.    >> There is now a -E option, which tells IconT to produce a .Exe file
  25.       instead of a .Icx file. (Case is significant; the -e option redirects
  26.       standard error.) All the other options still work the same way: the -c
  27.       option still works to produce linkable ucode, & if both -c & -E are
  28.       omitted a .Icx file is produced.
  29.    >> When the -E option is used with IconT, the file IconDOS.Exe must be
  30.       in the same directory as IconT.Exe.
  31. The .Exe file that IconT outputs can then be executed as a command at the DOS
  32. prompt or from inside a batch job, just like any other .Exe file.
  33. I/O redirection works normally. However, altho IconX.Exe need no longer be
  34. invoked as a command to run the new Icon program--the new Icon program itself
  35. is the command--IconX.Exe must be in one of the directories on the DOS Path.
  36.  
  37. This is what is needed to install this patch.
  38.    >> You must already have set up the directories & files for Making the
  39.       Icon interpretive system (IconT & IconX). How to do this is described
  40.       in the document IPD205.Doc, timestamp 11/19/92 16:13, which comes with
  41.       the Icon v8.8 for MS-DOS distribution. When I refer to files in this
  42.       article, I'll use absolute paths that will be correct iff you installed
  43.       the Icon hierarchy with \Icon as its root; this is also the assumption
  44.       made in IPD205.Doc. In both cases, that's just illustrative; what
  45.       really matters is the relative path below \Icon (or wherever).
  46.    >> You must have Maked & installed a working IconT & IconX as described in
  47.       sections 3 & 4 of IPD205.Doc. Note that the Icon distribution comes
  48.       with its own Make.Exe to run its Makefiles, & those Makefiles are not
  49.       compatible with the Borland C++ 3.1 Make.Exe. When you run an Icon
  50.       Make, you need to cause the directory containing Icon's Make.Exe to
  51.       precede the directory containing your C compiler's Make.Exe on the DOS
  52.       Path, even tho you'll probably also require that your C compiler's
  53.       directory be on Path.
  54.    >> You must modify the following 7 files in the Icon hierarchy:
  55.          \Icon\Src\h\Config.h
  56.          \Icon\Src\IconT\Globals.h
  57.          \Icon\Src\IconT\LCode.c
  58.          \Icon\Src\IconT\Link.c
  59.          \Icon\Src\IconT\TMain.c
  60.          \Icon\Src\Runtime\Init.r
  61.          \Icon\Src\Runtime\Init.r
  62.       The list of modifications takes up most of the rest of this article.
  63.    >> You must then reMake both IconT & IconX by following steps 1-3 on page
  64.       6 of IPD205.Doc.
  65.    >> You must create the following new file in the Icon hierarchy:
  66.          \Icon\Src\Runtime\IconDOS.c
  67.       Its text is at the end of this article.
  68.    >> You must compile that IconDOS.c to produce IconDOS.Exe. How you do that
  69.       depends on your particular compiler, but since IconDOS.c is pure
  70.       vanilla C, whatever compiler options you used for the other C source
  71.       files in the Icon interpreter system should work, except that you
  72.       should use the Small memory model instead of Large. (Don't use the Tiny
  73.       model, which produces a .Com file--it won't work.) If you have an
  74.       optimizing C compiler, I recommend fully optimizing for size. Omit
  75.       debugging information; by the time you produce an executable .Exe, that
  76.       information would have been clobbered anyway. IconDOS.Exe is not
  77.       intended to be a runnable program, but since it looks to MS-DOS like
  78.       one, its behavior when you run it can test that you compiled it
  79.       correctly. It should produce an error message like this:
  80.          error in startup code
  81.          C:\ICON\BIN\ICONDOS.EXE: can't read interpreter file header
  82.       Anything else (except a different path) means the compilation failed.
  83.       IconDOS.Exe must be compiled into the directory that contains
  84.       IconT.Exe, or moved into that directory after compilation. Intermediate
  85.       files from the compilation, like IconDOS.{Obj,Map}, can be deleted.
  86. After you've done all of this, the -E option to IconT should work.
  87.  
  88. In the following patch descriptions, a form like this
  89.    ======Cut Here: \Dir\Name.Ext [replace 6-9]======
  90.    line1
  91.    line2
  92.    line3
  93.    --------------------Cut Here---------------------
  94. means that in the file \Dir\Name.Ext, the 4 lines numbered 6-9 are to be
  95. deleted, then replaced by the 3 lines
  96.    line1
  97.    line2
  98.    line3
  99. shown explicitly. Everything shown between the "Cut Here" lines is to be
  100. inserted as is into the file; only the "Cut Here" lines are metadata.
  101. The form
  102.    ======Cut Here: \Dir\Name.Ext [precede 88]======
  103.    line4
  104.    line5
  105.    --------------------Cut Here---------------------
  106. is similar, but nothing is to be deleted; the lines between the "Cut Here"
  107. lines are just to be inserted before line 88.
  108.  
  109. ============Cut Here: \Icon\Src\h\Config.h [replace 797-833]==========
  110. #ifndef Options
  111. #ifndef Xver
  112. #if ARM || UNIX
  113. #define Options "C:LS:Tce:f:mn:o:p:r:stuv:x"
  114. #else                                   /* ARM || UNIX */
  115. #if MSDOS
  116. #define Options "C:ELS:Tce:f:n:o:p:r:stuv:x"
  117. #else                                   /* MSDOS */
  118. #define Options "C:LS:Tce:f:n:o:p:r:stuv:x"
  119. #endif                                  /* MSDOS */
  120. #endif                                  /* ARM || UNIX */
  121. #else                                   /* Xver */
  122. xver(config.3)
  123. #endif                                  /* Xver */
  124. #endif                                  /* Options */
  125.  
  126. #ifndef CUsage
  127. #if UNIX
  128. #define CUsage "[-C C-comp] [-T] [-c] [-f{adelns}] [-m] [-n{acest}]\n\
  129.  [-o ofile] [-p C-opts] [-r runtime] [-s] [-t] [-u] [-v i]"
  130. #else                                   /* UNIX */
  131. #define CUsage "[-C C-comp] [-T] [-c] [-f{adelns}] [-n{acest}]\n\
  132.  [-o ofile] [-p C-opts] [-r runtime] [-s] [-t] [-u] [-v i]"
  133. #endif                                  /* UNIX */
  134. #endif                                  /* CUsage */
  135.  
  136. #ifndef TUsage
  137. #ifndef Xver
  138. #if ARM || UNIX
  139. #define TUsage "[-cmstu] [-e efile] [-o ofile]"
  140. #else                                   /* ARM || UNIX */
  141. #if MVS || VM
  142. #define TUsage "<-cstu> <-e efile> <-o ofile>"
  143. #else                                   /* MVS || VM */
  144. #if MSDOS
  145. #define TUsage "[-cstuE] [-e efile] [-o ofile]"
  146. #else                                   /* MSDOS */
  147. #define TUsage "[-cstu] [-e efile] [-o ofile]"
  148. #endif                                  /* MSDOS */
  149. #endif                                  /* MVS || VM */
  150. #endif                                  /* ARM || UNIX */
  151. #else                                   /* Xver */
  152. xver(config.4)
  153. #endif                                  /* Xver */
  154. #endif                                  /* TUsage */
  155. -----------------------Cut Here---------------------
  156. =========Cut Here: \Icon\Src\IconT\Globals.h [precede 47]========
  157.  
  158. #if MSDOS
  159. Global int makeExe      Init(0);        /* -E: Create .Exe instead of .Icx */
  160. Global long fileOffsetOfStuffThatGoesInICX
  161.                         Init(0);        /* Remains 0 if -E not used */
  162.                                         /* set in link.c, used in lcode.c */
  163. #endif
  164. -----------------------Cut Here---------------------
  165. ==========Cut Here: \Icon\Src\Runtime\Init.r [replace 273-331]========
  166.  
  167. #if MSDOS
  168.    int thisIsAnExeFile = 0;
  169.    char bytesThatBeginEveryExe[2] = {0,0};
  170.    unsigned originalExeBytesMod512, originalExePages;
  171.    unsigned long originalExeBytes;
  172. #endif                                  /* MSDOS */
  173.  
  174.    if (!name)
  175.       error(name, "no interpreter file supplied");
  176.  
  177.    /*
  178.     * Try adding the suffix if the file name doesn't end in it,
  179.     * unless this is a MSDOS .Exe file (which already has the ".Exe").
  180.     */
  181.  
  182.    n = strlen(name);
  183.  
  184. #if MSDOS
  185.    if (n >= 4 && !stricmp(".Exe", name + n - 4)) {
  186.       thisIsAnExeFile = 1;
  187.       fname = pathOpen(name, ReadBinary);
  188.          /*
  189.           * IconDOS's code for calling IconX from an .Exe passes IconX the
  190.           * full path of the .Exe, so using pathOpen() seems redundant &
  191.           * potentially inefficient. However, pathOpen() first checks for a
  192.           * complete path, & if one is present, doesn't search Path; & since
  193.           * MS-DOS has a limited line length, it'd be possible for IconDOS
  194.           * to check whether the full path will fit, & if not, use only the
  195.           * name. The only price for this additional robustness would be
  196.           * the time pathOpen() spends checking for a path, which is trivial.
  197.           */
  198.       }
  199.    else {
  200. #endif                                  /* MSDOS */
  201.  
  202.       if (n <= 4 || (strcmp(name+n-4,IcodeSuffix) != 0)
  203.       && strcmp(name+n-4,IcodeASuffix) != 0) {
  204.          char tname[100];
  205.          if ((int)strlen(name) + 5 > 100)
  206.             error(name, "icode file name too long");
  207.          strcpy(tname,name);
  208.  
  209. #if MVS
  210.          { /*Begin MVS block*/
  211.             char *p;
  212.             if (p = index(name, '(')) {
  213.                tname[p-name] = '\0';
  214.                }
  215. #endif                                  /* MVS */
  216.  
  217.          strcat(tname,IcodeSuffix);
  218.  
  219. #if MVS
  220.             if (p) strcat(tname,p);
  221.             } /*End MVS block*/
  222. #endif                                  /* MVS */
  223.  
  224. #if MSDOS || OS2
  225.          fname = pathOpen(tname,ReadBinary);    /* try to find path */
  226. #else                                   /* MSDOS || OS2 */
  227.          fname = fopen(tname, ReadBinary);
  228. #endif                                  /* MSDOS || OS2 */
  229.          } /* end if (n <= 4 || etc for 2 lines */
  230.  
  231.       if (fname == NULL)                /* try the name as given */
  232.  
  233. #if MSDOS || OS2
  234.          fname = pathOpen(name, ReadBinary);
  235. #else                                   /* MSDOS || OS2 */
  236.          fname = fopen(name, ReadBinary);
  237. #endif                                  /* MSDOS || OS2 */
  238.  
  239. #if MSDOS
  240.       } /* end if (n >= 4 && !stricmp(".Exe", name + n - 4)) */
  241. #endif
  242.  
  243.    if (fname == NULL)
  244.       return NULL;
  245.  
  246. #ifdef Xver
  247. xver(imain.9)
  248. #endif                                  /* Xver */
  249.  
  250.    {
  251.    static char errmsg[] = "can't read interpreter file header";
  252.    static char exe_errmsg[] = "can't read MS-DOS .Exe header";
  253.  
  254. #ifdef Header
  255.  
  256. #if MSDOS
  257.    #error
  258.    deliberate syntax error
  259.  
  260.   /*
  261.    * The MSDOS .Exe-handling code assumes & requires that the executable
  262.    * .Exe be followed immediately by the icode itself (actually header.h).
  263.    * This is because the following Header fseek() is relative to the
  264.    * beginning of the file, which in a .Exe is the beginning of the
  265.    * executable code, not the beginning of some Icon thing; & I can't
  266.    * check & fix all the Header-handling logic because hdr.h wasn't
  267.    * included with my MS-DOS distribution so I don't even know what it does,
  268.    * let alone how to keep from breaking it. We're safe as long as
  269.    * Header & MSDOS are disjoint.
  270.    */
  271.  
  272. #endif                                  /* MSDOS */
  273.  
  274.    if (fseek(fname, (long)MaxHeader, 0) == -1)
  275.       error(name, errmsg);
  276.  
  277. #endif                                  /* Header */
  278.  
  279. #if MSDOS
  280.    if (thisIsAnExeFile) {
  281.       fread (&bytesThatBeginEveryExe, sizeof bytesThatBeginEveryExe, 1, fname);
  282.       if (bytesThatBeginEveryExe[0] != 'M' ||
  283.           bytesThatBeginEveryExe[1] != 'Z')
  284.          error(name, exe_errmsg);
  285.       fread (&originalExeBytesMod512, sizeof originalExeBytesMod512, 1, fname);
  286.       fread (&originalExePages,       sizeof originalExePages,       1, fname);
  287.       originalExeBytes = (originalExePages - 1)*512 + originalExeBytesMod512;
  288.       if (fseek(fname, originalExeBytes, 0))
  289.          error(name, errmsg);
  290.       if (ferror(fname) || feof(fname) || !originalExeBytes)
  291.          error(name, exe_errmsg);
  292.       }
  293. #endif                                  /* MSDOS */
  294. -----------------------Cut Here---------------------
  295. Next file is changed in 2 places.
  296. Second change is stated in terms of lines in v8.8 file ("old")
  297. and equivalently of lines in that file after first change ("new").
  298. ==========Cut Here: \Icon\Src\IconT\LCode.c [precede 47]=========
  299.  
  300. #if MSDOS
  301. extern long fileOffsetOfStuffThatGoesInICX;
  302.   /* defined in Globals.h, set in link.c, used below */
  303. #endif                                  /* MSDOS */
  304. ====Cut Here: \Icon\Src\IconT\LCode.c [replace old 1164-6 = new 1169-71]====
  305. #else
  306. #if MSDOS
  307.    fseek(outfile, fileOffsetOfStuffThatGoesInICX, 0);
  308. #else
  309.    fseek(outfile, 0L, 0);
  310. #endif                                  /* MSDOS */
  311. #endif                                  /* MVS */
  312. -----------------------Cut Here---------------------
  313. Next file is changed in 2 places.
  314. Second change is stated in terms of lines in v8.8 file ("old")
  315. and equivalently of lines in that file after first change ("new").
  316. ===========Cut Here: \Icon\Src\IconT\Link.c [precede 75]=========
  317.  
  318. #ifdef MSDOS
  319.    extern char pathToIconDOS[];
  320. #endif                                  /* MSDOS */
  321. ========Cut Here: \Icon\Src\IconT\Link.c [precede old 227 = new 231]======
  322.  
  323. #ifdef MSDOS
  324.  
  325.    /*
  326.     * This prepends IconDOS.Exe to outfile, so it'll be executable.
  327.     *
  328.     * I don't know what that #if Header stuff was about since my MSDOS
  329.     * distribution didn't include "hdr.h", but it looks very similar to
  330.     * what I'm doing, so I'll put my stuff here, & if somebody who
  331.     * understands all the multi-operating-system porting thinks my code could
  332.     * be folded into it, having it here should make it easy.
  333.     */
  334.  
  335.    if (makeExe) {
  336.       FILE *fIconDOS = fopen (pathToIconDOS, "rb");
  337.       char bytesThatBeginEveryExe[2] = {0,0}, oneChar;
  338.       unsigned originalExeBytesMod512, originalExePages;
  339.       unsigned long originalExeBytes, byteCounter;
  340.  
  341.       if (!fIconDOS)
  342.          quit("unable to find IconDOS.Exe in same dir as IconT");
  343.       if (setvbuf(fIconDOS, 0, _IOFBF, 4096))
  344.          if (setvbuf(fIconDOS, 0, _IOFBF, 128))
  345.             quit("setvbuf() failure");
  346.       fread (&bytesThatBeginEveryExe, 2, 1, fIconDOS);
  347.       if (bytesThatBeginEveryExe[0] != 'M' ||
  348.           bytesThatBeginEveryExe[1] != 'Z')
  349.          quit("IconDOS header is corrupt");
  350.       fread (&originalExeBytesMod512, sizeof originalExeBytesMod512,
  351.             1, fIconDOS);
  352.       fread (&originalExePages,       sizeof originalExePages,
  353.             1, fIconDOS);
  354.       originalExeBytes = (originalExePages - 1)*512 + originalExeBytesMod512;
  355.       if (ferror(fIconDOS) || feof(fIconDOS) || !originalExeBytes)
  356.          quit("IconDOS header is corrupt");
  357.       fseek (fIconDOS, 0, 0);
  358.       for (byteCounter = 0; byteCounter < originalExeBytes; byteCounter++) {
  359.          oneChar = fgetc (fIconDOS);
  360.          if (ferror(fIconDOS) || feof(fIconDOS) || ferror(outfile))
  361.             quit("Error copying IconDOS.Exe");
  362.          fputc (oneChar, outfile);
  363.          }
  364.       fclose (fIconDOS);
  365.       fileOffsetOfStuffThatGoesInICX = ftell (outfile);
  366.       }
  367.  
  368. #endif                                  /* MSDOS */
  369. -----------------------Cut Here---------------------
  370. ==========Cut Here: \Icon\Src\IconT\TMain.c [replace 70-509]=========
  371.  
  372. #ifdef MSDOS
  373.    char pathToIconDOS[129];
  374. #endif                                  /* MSDOS */
  375.  
  376.  * The following code is operating-system dependent [@tmain.02].  Definition
  377.  *  of refpath.
  378.  */
  379.  
  380. #if PORT
  381.    /* something is needed */
  382. Deliberate Syntax Error
  383. #endif                                  /* PORT */
  384.  
  385. #if UNIX || AMIGA || ATARI_ST || MACINTOSH || MSDOS || MVS || OS2 || VM
  386. char *refpath = RefPath;
  387. #endif                                  /* UNIX ... */
  388.  
  389. #if VMS
  390. char *refpath = "ICON_BIN:";
  391. #endif                                  /* VMS */
  392.  
  393.  * End of operating-system specific code.
  394.  */
  395.  
  396. char *iconxloc;
  397.  
  398.  * getopt() variables
  399.  */
  400. extern int optindex;            /* index into parent argv vector */
  401. extern int optopt;              /* character checked for validity */
  402. extern char *optarg;            /* argument associated with option */
  403.  
  404.  *  main program
  405.  */
  406. novalue main(argc,argv)
  407. int argc;
  408. char **argv;
  409.    {
  410.    int nolink = 0;                      /* suppress linking? */
  411.    int errors = 0;                      /* translator and linker errors */
  412.    char **tfiles, **tptr;               /* list of files to translate */
  413.    char **lfiles, **lptr;               /* list of files to link */
  414.    char **rfiles, **rptr;               /* list of files to remove */
  415.    char *efile = NULL;                  /* stderr file */
  416.    char buf[MaxFileName];               /* file name construction buffer */
  417.    int c, n;
  418.    struct fileparts *fp;
  419.  
  420.  
  421. #if AMIGA
  422. #if AZTEC_C
  423.    struct Process *FindTask();
  424.    struct Process *Process = FindTask(0L);
  425.    ULONG stacksize = *((ULONG *)Process->pr_ReturnAddr);
  426.  
  427.    if (stacksize < ICONTMINSTACK) {
  428.       fprintf(stderr,"Icont needs \"stack %d\" to run\n",ICONTMINSTACK);
  429.       exit(-1);
  430.       }
  431. #endif                                  /* AZTEC_C */
  432. #endif                                  /* AMIGA */
  433.  
  434.  
  435. #if MACINTOSH
  436. #if MPW
  437.    InitCursorCtl(NULL);
  438.    SortOptions(argv);
  439. #endif                                  /* MPW */
  440. #endif                                  /* MACINTOSH */
  441.  
  442.    iconxloc = (char *)alloc((unsigned)strlen(refpath) + 6);
  443.    strcpy(iconxloc, refpath);
  444.    strcat(iconxloc, "iconx");
  445.  
  446.    if (strlen(patchpath)>18)
  447.       iconxloc = patchpath+18;
  448.  
  449.    /*
  450.     * Process options.
  451.     */
  452.    while ((c = getopt(argc,argv,Options)) != EOF)
  453.       switch (c) {
  454.          case 'C':                      /* Ignore: compiler only */
  455.             break;
  456.  
  457. #ifdef MSDOS
  458.          case 'E':                      /* -E */
  459.             makeExe = 1;
  460.             break;
  461. #endif
  462.  
  463. #ifdef Xver
  464. xver(tmain.1)
  465. #endif                                  /* Xver */
  466.  
  467.          case 'L':                      /* -L: enable linker debugging */
  468.  
  469. #ifdef DeBugLinker
  470.             Dflag = 1;
  471. #endif                                  /* DeBugLinker */
  472.  
  473.             break;
  474.  
  475.          case 'S':                      /* -S */
  476.             fprintf(stderr, "Warning, -S option is obsolete\n");
  477.             break;
  478.          case 'c':                      /* -c: compile only (no linking) */
  479.             nolink = 1;
  480.             break;
  481.          case 'e':                      /* -e file: redirect stderr */
  482.             efile = optarg;
  483.             break;
  484.          case 'f':                      /* Ignore: compiler only */
  485.             break;
  486.          case 'm':                      /* -m: preprocess using m4(1) [UNIX] */
  487.             m4pre = 1;
  488.             break;
  489.          case 'n':                      /* Ignore: compiler only */
  490.             break;
  491.          case 'o':                      /* -o file: name output file */
  492.             ofile = optarg;
  493.             break;
  494.  
  495.          case 'p':                      /* -p path: iconx path [ATARI] */
  496. #if ATARI_ST
  497.             patharg = optarg;
  498. #endif                                  /* ATARI_ST */
  499.             break;
  500.  
  501.          case 'r':                      /* Ignore: compiler only */
  502.             break;
  503.          case 's':                      /* -s: suppress informative messages */
  504.             silent = 1;
  505.             break;
  506.          case 't':                      /* -t: turn on procedure tracing */
  507.             trace = -1;
  508.             break;
  509.          case 'u':                      /* -u: warn about undeclared ids */
  510.             uwarn = 1;
  511.             break;
  512.          case 'v':                      /* Ignore: compiler only */
  513.             break;
  514.          default:
  515.          case 'x':                      /* -x illegal until after file list */
  516.             usage();
  517.          }
  518.  
  519.  
  520. #ifdef MSDOS
  521.  
  522.       /*
  523.        * Define pathToIconDOS as a global accessible from inside
  524.        * separately-compiled compilation units.
  525.        */
  526.  
  527.       if( makeExe ){
  528.          char *pathCursor;
  529.  
  530.          strcpy (pathToIconDOS, argv[0]);
  531.          pathCursor = strrchr (pathToIconDOS, '\\');
  532.          if (!pathCursor) {
  533.             fprintf (stderr,
  534.                "Can't understand what directory IconT was run from.\n");
  535.             exit(ErrorExit);
  536.             }
  537.             strcpy (++pathCursor, "IconDOS.Exe");
  538.          }
  539. #endif                                  /* MSDOS */
  540.  
  541.  
  542.    /*
  543.     * Allocate space for lists of file names.
  544.     */
  545.    n = argc - optindex + 1;
  546.    tptr = tfiles = (char **)alloc((unsigned int)(n * sizeof(char *)));
  547.    lptr = lfiles = (char **)alloc((unsigned int)(n * sizeof(char *)));
  548.    rptr = rfiles = (char **)alloc((unsigned int)(2 * n * sizeof(char *)));
  549.  
  550.    /*
  551.     * Scan file name arguments.
  552.     */
  553.    while (optindex < argc)  {
  554.       if (strcmp(argv[optindex],"-x") == 0)     /* stop at -x */
  555.          break;
  556.       else if (strcmp(argv[optindex],"-") == 0) {
  557.  
  558. #if ARM
  559.         /* Different file naming, so we need a different strategy... */
  560.         *tptr++ = "-";
  561.         /* Use makename(), pretending we had an input file named "Stdin" */
  562.         makename(buf,TargetDir,"Stdin",U1Suffix);
  563.         *lptr++ = *rptr++ = salloc(buf);        /* link & remove .u1 */
  564.         makename(buf,TargetDir,"Stdin",U2Suffix);
  565.         *rptr++ = salloc(buf);          /* also remove .u2 */
  566.  
  567. #else                                   /* ARM */
  568.  
  569.          *tptr++ = "-";                         /* "-" means standard input */
  570.          *lptr++ = *rptr++ = "stdin.u1";
  571.          *rptr++ = "stdin.u2";
  572. #endif                                  /* ARM */
  573.  
  574.          }
  575.       else {
  576.          fp = fparse(argv[optindex]);           /* parse file name */
  577.          if (*fp->ext == '\0' || smatch(fp->ext, SourceSuffix)) {
  578.             makename(buf,SourceDir,argv[optindex], SourceSuffix);
  579. #if VMS
  580.             strcat(buf, fp->version);
  581. #endif                                  /* VMS */
  582.             *tptr++ = salloc(buf);              /* translate the .icn file */
  583.             makename(buf,TargetDir,argv[optindex],U1Suffix);
  584.             *lptr++ = *rptr++ = salloc(buf);    /* link & remove .u1 */
  585.             makename(buf,TargetDir,argv[optindex],U2Suffix);
  586.             *rptr++ = salloc(buf);              /* also remove .u2 */
  587.             }
  588.          else if (smatch(fp->ext,U1Suffix) || smatch(fp->ext,U2Suffix)
  589.                || smatch(fp->ext,USuffix)) {
  590.             makename(buf,TargetDir,argv[optindex],U1Suffix);
  591.             *lptr++ = salloc(buf);
  592.             }
  593.          else
  594.             quitf("bad argument %s",argv[optindex]);
  595.          }
  596.       optindex++;
  597.       }
  598.  
  599.    *tptr = *lptr = *rptr = NULL;        /* terminate filename lists */
  600.    if (lptr == lfiles)
  601.       usage();                          /* error -- no files named */
  602.  
  603.    /*
  604.     * Round hash table sizes to next power of two, and set masks for hashing.
  605.     */
  606.    lchsize = round2(lchsize);  cmask = lchsize - 1;
  607.    fhsize = round2(fhsize);  fmask = fhsize - 1;
  608.    ghsize = round2(ghsize);  gmask = ghsize - 1;
  609.    ihsize = round2(ihsize);  imask = ihsize - 1;
  610.    lhsize = round2(lhsize);  lmask = lhsize - 1;
  611.  
  612.    /*
  613.     * Translate .icn files to make .u1 and .u2 files.
  614.     */
  615.    if (tptr > tfiles) {
  616.       if (!silent)
  617.          report("Translating");
  618.       errors = trans(tfiles);
  619.       if (errors > 0)                   /* exit if errors seen */
  620.          exit(ErrorExit);
  621.       }
  622.  
  623.    /*
  624.     * Link .u1 and .u2 files to make an executable.
  625.     */
  626.    if (nolink) {                        /* exit if no linking wanted */
  627.  
  628. #if MACINTOSH
  629. #if MPW
  630.       /*
  631.        *  Set type of translator output ucode (.u) files
  632.        *  to 'TEXT', so they can be easily viewed by editors.
  633.        */
  634.       {
  635.       char **p;
  636.       void setfile();
  637.       for (p = rfiles; *p; ++p)
  638.          setfile(*p,'TEXT','icon');
  639.       }
  640. #endif                                  /* MPW */
  641. #endif                                  /* MACINTOSH */
  642.  
  643.       exit(NormalExit);
  644.       }
  645.  
  646. #if MSDOS
  647.  
  648.    if (ofile == NULL)  {                /* if no -o file, synthesize a name */
  649.       ofile = salloc(makename(buf,TargetDir,lfiles[0],
  650.                               makeExe ? ".Exe" : IcodeSuffix));
  651.    } else {                             /* add extension if necessary */
  652.       fp = fparse(ofile);
  653.       if (*fp->ext == '\0' && *IcodeSuffix != '\0') /* if no ext given */
  654.          ofile = salloc(makename(buf,NULL,ofile,
  655.                                  makeExe ? ".Exe" : IcodeSuffix));
  656.    }
  657.  
  658. #else                                   /* MSDOS */
  659.  
  660.    if (ofile == NULL)  {                /* if no -o file, synthesize a name */
  661.       ofile = salloc(makename(buf,TargetDir,lfiles[0],IcodeSuffix));
  662.    } else {                             /* add extension if necessary */
  663.       fp = fparse(ofile);
  664.       if (*fp->ext == '\0' && *IcodeSuffix != '\0') /* if no ext given */
  665.          ofile = salloc(makename(buf,NULL,ofile,IcodeSuffix));
  666.    }
  667.  
  668. #endif                                  /* MSDOS */
  669.  
  670.    if (!silent)
  671.       report("Linking");
  672.    errors = ilink(lfiles,ofile);        /* link .u files to make icode file */
  673.  
  674.    /*
  675.     * Finish by removing intermediate files.
  676.     *  Execute the linked program if so requested and if there were no errors.
  677.     */
  678.  
  679. #if MACINTOSH
  680. #if MPW
  681.    /* Set file type to TEXT so it will be executable as a script. */
  682.    setfile(ofile,'TEXT','icon');
  683. #endif                                  /* MPW */
  684. #endif                                  /* MACINTOSH */
  685.  
  686.    rmfiles(rfiles);                     /* remove intermediate files */
  687.    if (errors > 0) {                    /* exit if linker errors seen */
  688.       unlink(ofile);
  689.       exit(ErrorExit);
  690.       }
  691.  
  692. #if !(MACINTOSH && MPW)
  693.    if (optindex < argc)  {
  694.       if (!silent)
  695.          report("Executing");
  696.       execute (ofile, efile, argv+optindex+1);
  697.       }
  698. #endif                                  /* !(MACINTOSH && MPW) */
  699.  
  700.    exit(NormalExit);
  701.    }
  702.  
  703.  * execute - execute iconx to run the icon program
  704.  */
  705. static novalue execute(ofile,efile,args)
  706. char *ofile, *efile, **args;
  707.    {
  708.  
  709. #if !(MACINTOSH && MPW)
  710.    int n;
  711.    char **argv, **p;
  712.  
  713.    for (n = 0; args[n] != NULL; n++)    /* count arguments */
  714.       ;
  715.    p = argv = (char **)alloc((unsigned int)((n + 5) * sizeof(char *)));
  716.  
  717.    *p++ = iconxloc;                     /* set iconx pathname */
  718.    if (efile != NULL) {                 /* if -e given, copy it */
  719.       *p++ = "-e";
  720.       *p++ = efile;
  721.       }
  722.    *p++ = ofile;                        /* pass icode file name */
  723.  
  724. #if AMIGA && LATTICE
  725.    *p = *args;
  726.    while (*p++) {
  727.       *p = *args;
  728.       args++;
  729.    }
  730. #else                                   /* AMIGA && LATTICE */
  731.    while (*p++ = *args++)               /* copy args into argument vector */
  732.       ;
  733. #endif                                  /* AMIGA && LATTICE */
  734.  
  735.    *p = NULL;
  736.  
  737.  * The following code is operating-system dependent [@tmain.03].  It calls
  738.  *  iconx on the way out.
  739.  */
  740.  
  741. #if PORT
  742.    /* something is needed */
  743. Deliberate Syntax Error
  744. #endif                                  /* PORT */
  745.  
  746. #if AMIGA
  747. #if AZTEC_C
  748.       execvp(iconxloc,argv);
  749.       return;
  750. #endif                                  /* AZTEC_C */
  751. #if LATTICE
  752.       {
  753.       struct ProcID procid;
  754.       if (forkv(iconxloc,argv,NULL,&procid) == 0) {
  755.          wait(&procid);
  756.          return;
  757.          }
  758.       }
  759. #endif                                  /* LATTICE */
  760. #endif                                  /* AMIGA */
  761.  
  762. #if ARM
  763.    {
  764.       int i = 7 + strlen(iconxloc);
  765.       int j;
  766.       char *s;
  767.       char buffer[255];
  768.       extern int armquote(char *, char **);
  769.  
  770.       sprintf(buffer, "Chain:%s ", iconxloc);
  771.       for (p = argv + 1; *p; ++p)
  772.       {
  773.          j = armquote(*p, &s);
  774.  
  775.          if (j == -1 || i + j >= 255)
  776.          {
  777.             fprintf(stderr, "Cannot execute: command line too long");
  778.             fflush(stderr);
  779.             return;
  780.          }
  781.  
  782.          strcpy(buffer + i, s);
  783.          i += j;
  784.          buffer[i] = ' ';
  785.       }
  786.       buffer[i] = '\0';
  787.       system(buffer);
  788.    }
  789. #endif                                  /* ARM */
  790.  
  791. #if ATARI_ST || MACINTOSH
  792.       fprintf(stderr,"-x not supported\n");
  793.       fflush(stderr);
  794. #endif                                  /* ATARI_ST || ... */
  795.  
  796. #if MSDOS
  797.       /*
  798.        * No special handling is needed for an .Exe, since IconX recognizes
  799.        * it from the extension & from internal .Exe header data.
  800.        */
  801. #if MICROSOFT || TURBO
  802.       execvp(iconxloc,argv);    /* execute with path search */
  803. #endif                                  /* MICROSOFT || ... */
  804. #if INTEL_386 || ZTC_386 || HIGHC_386 || WATCOM
  805.       fprintf(stderr,"-x not supported\n");
  806.       fflush(stderr);
  807. #endif                                  /* INTEL_386 || ... */
  808. #endif                                  /* MSDOS */
  809.  
  810. #if MVS || VM
  811. #if SASC
  812.           exit(sysexec(iconxloc, argv));
  813. #endif                                  /* SASC */
  814.       fprintf(stderr,"-x not supported\n");
  815.       fflush(stderr);
  816. #endif                                  /* MVS || VM */
  817.  
  818. #if OS2
  819.       execvp(iconxloc,argv);    /* execute with path search */
  820. #endif                                  /* OS2 */
  821.  
  822. #if UNIX
  823.       /*
  824.        * If an ICONX environment variable is defined, use that.
  825.        *  If not, first try the predefined path, then search $PATH via execvp.
  826.        */
  827.       if ((argv[0] = getenv("ICONX")) != NULL && argv[0][0] != '\0') {
  828.          execv(argv[0], argv);  /* exec file specified by $ICONX */
  829.          quitf("cannot execute $ICONX (%s)", argv[0]);
  830.          }
  831.  
  832. #ifdef HardWiredPaths
  833. #ifdef CRAY
  834.       argv[0] = "iconx";
  835.       execv(iconxloc, argv);
  836. #else                                   /* CRAY */
  837.       argv[0] = iconxloc;               /* try predefined file */
  838.       execv(argv[0], argv);
  839. #endif                                  /* CRAY */
  840. #endif                                  /* HardWiredPaths */
  841.  
  842.       argv[0] = "iconx";
  843.       execvp(argv[0], argv);    /* if no iconxloc, search path for "iconx" */
  844.  
  845. #ifdef HardWiredPaths
  846.       quitf("cannot run %s", iconxloc);
  847. #else                                   /* HardWiredPaths */
  848.       quitf("cannot find iconx", "");
  849. #endif                                  /* HardWiredPaths */
  850. #endif                                  /* UNIX */
  851.  
  852. #if VMS
  853.       execv(iconxloc,argv);
  854. #endif                                  /* VMS */
  855.  
  856.  * End of operating-system specific code.
  857.  */
  858. -----------------------Cut Here---------------------
  859. ==========Cut Here: \Icon\Src\Runtime\IconDOS.c [create]========
  860.  * IconDOS.c -- Header for MS-DOS Icon *.Exe (executable) file
  861.  */
  862.  
  863. #include <stdio.h>
  864. #include <string.h>
  865. #include <alloc.h>
  866. #include <process.h>
  867.  
  868. int main( int argc, char **argv ){
  869.   char *argsToIconX[129], **argsToIconXCursor, **argvCursor;
  870.  
  871.   argsToIconXCursor = argsToIconX; argvCursor = argv;
  872.   *argsToIconXCursor++ = "IconX";
  873.   while( argc-- ) *argsToIconXCursor++ = *argvCursor++;
  874.   *argsToIconXCursor++ = 0;
  875.  
  876. ; execvp( "IconX", argsToIconX );
  877.  
  878.   perror( "Couldn't execvp( \"IconX\", ... )" );
  879. ; return 250;
  880. }
  881. -----------------------Cut Here---------------------
  882.  
  883. My office computer doesn't have a modem, & I usually sleep at the office for
  884. a week at a time, so I'll be slow to respond to e-mail & slower to snailmail.
  885. I try to read comp.lang.icon weekly, but sometimes I miss it. I've had 2
  886. reports of e-mail messages getting lost, & snailmail is also unreliable.
  887. Please don't misconstrue these communications difficulties as signs of
  888. disinterest; I'll try to respond to anyone who needs help getting this patch
  889. installed, or who reports bugs or suggests enhancements.
  890.  
  891. Will Mengarini; 4739 University Wy NE #1001; Seattle WA 98105-4495
  892. mengarini@delphi.com                                  206\632-4130
  893.